home *** CD-ROM | disk | FTP | other *** search
- /*
- * misc.c - misc utility routines
- *
- * Copyright 1992-1993 Merit Network, Inc. and The Regents of the
- * University of Michigan. Usage of this source code is restricted
- * to non-profit, non-commercial purposes. The source is provided
- * "as-is", without warranty.
- *
- * Warning! Some of these routines assume a BIG-ENDIAN architecture
- * (i.e. the 68K) and are thus machine specific.
- *
- * Some of these routines were derived from similar functions in
- * KA9Q which are Copyright Phil Karn. The code in these routines
- * have been substantially modified for the sake of efficiency.
- */
-
- #include "ppp.h"
-
- /* define LOG in ppp.h to compine in logging code */
- #ifdef LOG
- void log(LapInfo *lap, int rtn, int state, int code, int prot)
- {
- *(lap->logp)++ = rtn;
- *(lap->logp)++ = state;
- *(lap->logp)++ = code;
- *(lap->logp)++ = prot;
- if (lap->logp > &(lap->logend))
- lap->logp = &(lap->log[0]);
- }
- #endif
-
- void AppendStr(unsigned char *dst, unsigned char *src)
- {
- unsigned char dl, sl;
-
- dl = *dst;
- sl = *src++;
- *dst++ += sl;
- BlockMove(src, dst + dl, sl);
- }
-
- struct bufheader *
- getbuffer ()
- {
- LapInfo *lap;
- short savsr;
- int i;
- struct bufheader *bufptr;
-
- lap = GetLAPPtr();
- savsr = set_sr(0x2100); /* Disable timer ints */
- bufptr = lap->buflist;
- if (bufptr != nil) {
- lap->buflist = (struct bufheader *) bufptr->dataptr;
- bufptr->dataptr = ((unsigned char *) bufptr) + BUFOFFSET;
- bufptr->length = 0;
- } else {
- PPP_DEBUG_CHECKS("\pOut of buffers!");
- lap->OutofBuffers++;
- }
-
- set_sr(savsr); /* Re-enable ints */
- return (bufptr);
- }
-
- /* routine to put a buffer back on the free list */
- void
- release( struct bufheader *bufptr )
- {
- LapInfo *lap;
- short savsr;
-
- if (bufptr == nil)
- return; /* already released */
- lap = GetLAPPtr();
- savsr = set_sr(0x2100); /* Disable timer ints */
- bufptr->dataptr = (unsigned char *) lap->buflist;
- lap->buflist = bufptr;
- set_sr(savsr); /* restore ints */
- }
-
- void
- makeroom(struct bufheader *bufptr, b_16 room)
- {
- bufptr->length += room;
- bufptr->dataptr -= room;
- }
-
- /* yank off the desired number of byte from buffer
- Return number of bytes yanked
- */
- b_16
- yankbuf(register struct bufheader *bufptr, b_8 *yankbuf, b_16 count)
- {
- register b_16 yanked;
-
- yanked = count > bufptr->length ? bufptr->length : count;
- BlockMove(bufptr->dataptr, yankbuf, (long) yanked);
- bufptr->dataptr += yanked;
- bufptr->length -= yanked;
- return (yanked);
- }
- /* Yank a 32-bit integer from a buffer.
- * 0 is returned on error, but it cannot be distinguished from a good call.
- */
- b_32
- yank32(struct bufheader *bufptr)
- {
- b_32 rvalue;
-
- if (yankbuf(bufptr, (b_8 *) &rvalue, 4) < 4)
- return 0;
- return rvalue;
- }
- /* Yank a 16-bit integer in host order from buffer in network byte order.
- * Return -1 on error
- */
- long
- yank16(struct bufheader *bufptr)
- {
- b_16 rvalue;
-
- if (yankbuf(bufptr, (b_8 *) &rvalue, 2) < 2)
- return -1;
- return (unsigned long) rvalue;
- }
-
- /* yank a single byte from buffer, return -1 on error */
- short
- yankbyte(struct bufheader *bufptr)
- {
- if ( bufptr->length == 0) /* no data */
- return -1;
- bufptr->length--; /* decrement length */
- return (*bufptr->dataptr++);
- }
-
- /*
- * getipheader() - pull IP header off a packet
- */
- short
- getipheader(struct ipheader *header, struct bufheader *bufptr)
- {
- short headlen, optlen;
-
- yankbuf(bufptr, (b_8 *) header, IPHLEN);
- headlen = ( header->version & 0x0f ) << 2;
- if ( (optlen = headlen - IPHLEN) > 0 )
- yankbuf(bufptr, (b_8 *) header->options, optlen); /* copy options, if any */
- return headlen;
- }
-
- /*
- * putipheader() - put an IP header on a packet
- */
- void
- putipheader(struct ipheader *header, struct bufheader *bufptr)
- {
- b_16 headlen;
-
- headlen = ( header->version & 0x0f) << 2;
- bufptr->dataptr -= headlen;
- bufptr->length += headlen;
- BlockMove(header, bufptr->dataptr, headlen);
- }
-
- /*
- * gettcpheader() - pull TCP header off a packet
- */
- short
- gettcpheader(struct tcpheader *header, struct bufheader *bufptr)
- {
- short headlen, optlen;
-
- yankbuf(bufptr, (b_8 *) header, TCPHLEN); /* copy the data */
- headlen = ( header->offset & 0xf0 ) >> 2;
- if ( (optlen = headlen - TCPHLEN) > 0 )
- yankbuf(bufptr, header->options, optlen); /* copy options, if any */
- return headlen;
- }
-
- /*
- * puttcpheader() - put an TCP header on a packet
- */
- void
- puttcpheader(struct tcpheader *header, struct bufheader *bufptr)
- {
- short headlen;
-
- headlen = ( header->offset & 0xf0 ) >> 2;
- bufptr->dataptr -= headlen;
- bufptr->length += headlen;
- BlockMove(header, bufptr->dataptr, headlen);
- }
-
- /*
- * tcp_window_fix() - window size changer to improve MacTCP performance
- *
- * Below we define the max window size to allow. 2920 corresponds to
- * 2 full-size seqments and seems to be a good number to use
- */
- #define MAXWIN 2920
- void
- tcp_window_fix(LapInfo *lap, struct bufheader *bufptr)
- {
- register b_16 windiff, winsize, checksum, winmax;
- b_8 *tcpptr;
-
- winmax = lap->prefdata.max_window;
-
- /* Check if TCP and not part of a fragment */
- if (*(bufptr->dataptr + IP_PROTO_OFFSET) == TCP_PROTOCOL &&
- (get16(bufptr->dataptr + IP_OFFSET_OFFSET) & 0x1fff) == 0){
- /* get TCP header */
- tcpptr = bufptr->dataptr + ((*bufptr->dataptr & 0x0f) << 2) + 14L;
- winsize = get16(tcpptr);
- if (winsize > winmax) { /* check if window is too big */
- windiff = winsize - winmax;
- tcpptr = put16(tcpptr, winmax);
- checksum = ~get16(tcpptr); /* need to fix the checksum */
- if ( windiff >= checksum )
- checksum--;
- checksum -= windiff;
- put16(tcpptr, ~checksum);
- }
- }
- }
-
- /* simple/stupid byte compare routine */
- /* return 0 if equal, -1 if not */
- short
- bytecmp(b_8 *s1, b_8 *s2, short n)
- {
- for ( ; n>0 ; n--) {
- if (*s1++ != *s2++)
- return -1;
- }
- return 0;
- }
-
- /* Put a long in host order into a char array in network order */
- b_8 *
- put32(b_8 *cp, b_32 x)
- {
- b_8 *ptr = (b_8 *) &x;
-
- *cp++ = *ptr++;
- *cp++ = *ptr++;
- *cp++ = *ptr++;
- *cp++ = *ptr;
- return cp;
- }
- b_32
- get32(b_8 *cp)
- {
- b_32 rval;
- b_8 *ptr = (b_8 *) &rval;
-
- *ptr++ = *cp++;
- *ptr++ = *cp++;
- *ptr++ = *cp++;
- *ptr = *cp;
-
- return rval;
- }
- #pragma options(honor_register) /* Make Think C honor registers */
- /* Put a short in host order into a char array in network order */
- b_8 *
- put16(register b_8 *cp, b_16 x)
- {
- register b_8 *ptr = (b_8 *) &x;
-
- *cp++ = *ptr++;
- *cp++ = *ptr;
-
- return cp;
- }
- b_16
- get16(register b_8 *cp)
- {
- b_16 rval;
- register b_8 *ptr = (b_8 *) &rval;
-
- *ptr++ = *cp++;
- *ptr = *cp;
-
- return rval;
- }
-